﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Linq;
using Innoapps.FileTransfer.Models;
using Renci.SshNet;

namespace Innoapps.FileTransfer.Adapters.Send
{
    public class SFTP : Base
    {

        #region
        public enum SftpClientAuthenticationModes
        {
            Password = 1,
            PublicKeyAuthentication = 2
        }


        #endregion

        #region Properties

        [XmlAttribute("uri")]
        public override string uri
        {
            get
            {
                return "sftp://"
                    + UserName
                    + (UserName != "" && Password != "" ? ":" : "")
                    + (UserName != "" || Password != "" ? "@" : "")
                    + Path.Combine(Path.Combine(Server, FolderPath), FileName);
            }
            set
            {
                Uri u = new Uri(value);

                UserName = u.UserInfo != "" ? u.UserInfo.Split(':')[0] : UserName;
                Password = u.UserInfo != "" && u.UserInfo.Contains(":") ? u.UserInfo.Split(':')[1] : Password;
                Server = u.Host;
                Port = u.Port;
                if(u.IsFile)
                    FileName = Path.GetFileName(u.LocalPath);

                FolderPath = Path.GetDirectoryName(u.LocalPath);

            }
        }

        [XmlAttribute("Password")]
        public string Password { get; set; }
        [XmlAttribute("Port")]
        public int Port { get; set; }
        [XmlAttribute("Server")]
        public string Server { get; set; }
        [XmlAttribute("UserName")]
        public string UserName { get; set; }
        [XmlAttribute("AcceptAnySSHServerHostKey")]
        public Boolean AcceptAnySSHServerHostKey { get; set; }
        [XmlAttribute("ClientAuthenticationMode")]
        public SftpClientAuthenticationModes ClientAuthenticationMode { get; set; }
        [XmlAttribute("PrivateKey")]
        public string PrivateKey { get; set; }
        [XmlAttribute("PrivateKeyPassword")]
        public string PrivateKeyPassword { get; set; }
        [XmlAttribute("SSHServerHostKeyFingerPrint")]
        public string SSHServerHostKeyFingerPrint { get; set; }

        [XmlAttribute("FolderPath")]
        public string FolderPath { get; set; }
        [XmlAttribute("FileName")]
        public string FileName { get; set; }

        [XmlAttribute("TemporaryFolder")]
        public string TemporaryFolder { get; set; }

        #endregion

        #region Methods
        public override void Send()
        {
            try
            {

                Stream stream;
                string uri = this.uri;
                SftpClient client;
                ConnectionInfo connectionInfo;

                if (ClientAuthenticationMode == SftpClientAuthenticationModes.Password)
                {
                    connectionInfo = new PasswordConnectionInfo(Server, Port, UserName, Password);
                }
                else
                {
                    PrivateKeyFile privateKeyFile = new PrivateKeyFile(PrivateKey, PrivateKeyPassword);
                    connectionInfo = new PrivateKeyConnectionInfo(Server, UserName, privateKeyFile);
                }

                client = new SftpClient(connectionInfo);

                client.Connect();

                stream = new MemoryStream();

                if (TemporaryFolder != "")
                {

                    client.UploadFile(transfer.Stream, Path.Combine(TemporaryFolder, FileName));

                    Renci.SshNet.Sftp.SftpFile file = client.Get(Path.Combine(TemporaryFolder, FileName));

                    file.MoveTo(Path.Combine(FolderPath, FileName));

                }
                else
                {
                    client.UploadFile(transfer.Stream, Path.Combine(FolderPath, FileName));
                }

                Pass();
            }
            catch (Exception e)
            {
                Fail(e.Message);
            }
        }

        #endregion

    }
}
